package me.liuyu2783.dubbo.netty_impl;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;

import java.lang.reflect.Method;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * me.liuyu2783.dubbo.netty_impl
 *
 * @author liuyu2783
 * @date 2020-2-29
 */
public class NettyServer {

    List serviceList = new ArrayList<>();

    //1、http服务实现
    public void openServer(int port) throws InterruptedException {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.channel(NioServerSocketChannel.class);
        EventLoopGroup mainGroup = new NioEventLoopGroup(1);
        EventLoopGroup workGroup = new NioEventLoopGroup(8);
        serverBootstrap.group(mainGroup, workGroup);
        serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {
            @Override
            protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                //初始化netty的管道
                nioSocketChannel.pipeline().addLast("http-code", new HttpRequestDecoder());
                nioSocketChannel.pipeline().addLast("http-aggregator", new HttpObjectAggregator(1));
                nioSocketChannel.pipeline().addLast("http-encode", new HttpResponseEncoder());
                nioSocketChannel.pipeline().addLast("servlet", new ServletHandler());
            }
        });
        ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
        System.out.println("服务已开启");
        channelFuture.channel().closeFuture().sync();
    }

    public class ServletHandler extends SimpleChannelInboundHandler<FullHttpRequest>{

        @Override
        protected void channelRead0(ChannelHandlerContext channelHandlerContext, FullHttpRequest fullHttpRequest) throws Exception {
            //解析url
            URI uri = new URI(fullHttpRequest.uri());
            //http://120.0.0.1:8081/me.liuyu2783.peyService/getPetName
            String serverName = uri.getPath().split("/")[0];
            String methodName = uri.getPath().split("/")[1];
            //查账方法
            try {
                Object result = findMethod(serverName,methodName).apply(fullHttpRequest.content());
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }

            //业务处理
            FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
            httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/html;charset=utf-8");
            httpResponse.content().writeBytes("您好".getBytes());
            channelHandlerContext.writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);
        }
    }

    /**
     * 反序列化
     */
    private Object[] deserialArgs(Method method, ByteBuf byteBuf){
        byte[] bytes = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(bytes);

//        Map map = UtilJSON.toMap(new String(bytes));
        String[] names = Arrays.stream(method.getParameters()).map(p->p.getName()).collect(Collectors.toList()).toArray(new String[]{});
        Class<?>[] types = method.getParameterTypes();
        Object[] args = new Object[names.length];
        for(int i =0; i < names.length; i ++){
//            args[i] = UtilJSON.convertValue();
        }
        return args;
    }

    //查找方法
    public Function<ByteBuf,Object> findMethod(String serverName, String methodName) throws Throwable {
        Object server = serviceList.stream().filter(s->s.getClass().getName().equalsIgnoreCase(serverName))
                .findFirst()
                .orElseThrow(()-> new IllegalArgumentException("没有找到服务"));
        Method method = Arrays.stream(server.getClass().getMethods()).filter(m -> m.getName().equalsIgnoreCase(methodName))
                .findFirst()
                .orElseThrow(()-> new IllegalArgumentException("没有找到方法"));
        return args -> {
            try{
                return method.invoke(server, deserialArgs(method, args));
            }catch (Exception e){

            }
            return  null;
        };
    }

    public static void main(String[] args) {
        try {
            new NettyServer().openServer(8181);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
